Verklaring van de werking:
De voeding voor de schakeling wordt betrokken uit de start batterij (via een 78L05 spanningsregelaar).
De spanning die gemeten wordt, is die van de lichtbatterij of van de combinatie licht/startbatterij (als de brug
aan staat). De spanning wordt gemeten m.b.v. een spanningsdeler gevormd door R3/R4 om binnen 5V te blijven. De maximale
ingangsspanning bedraagt 15V (voldoende voor de situatie waarbij de batterij maximaal is opgeladen en er volop
zonlicht is).
Als de spanning onder 12,4 volt komt, wordt de brug uit gezet. Komt de spanning boven 13,5 volt, wordt de brug
aan gezet. Tussen deze twee waarden wordt de brug gelaten zoals hij was (dat kan dus zowel aan als uit zijn,
afhankelijk of men van de "hoge" kant komt dan wel de "lage").
De werking berust op het gebruik van 2 opamps die de spanning vergelijken met een vooraf ingestelde spanning.
De ene opamp wordt gebruikt voor de "lage" drempel, de andere voor de "hoge" drempel. Het resultaat is telkens 0 of
1 (eronder of erover) en de twee uitgangen van de opamps worden naar de ingang van een microprocessor gestuurd
die de sturing van de brug softwarematig afhandelt.
De twee opamps vinden we in IC LM324 dewelke er vier behuist, ruim voldoende dus.
De lage drempel en de hoge drempel kunnen best op ca. 12,4 resp. 13,5 volt staan, instellen kan via resp. POT1 en
POT2.
De brug zelf bestaat uit een zgn. bistabiele relais die twee spoelen heeft (een voor uit en een voor aan). Dit relais
heeft een spoelspanning van 12V en een schakelstroomsterkte van 12A bij 12V.
Het contact gedeelte van de brug is in het schema niet getoond, je moet gewoon het maak-contact van het relais
gebruiken en een uiteinde met de startbatterij verbinden, het andere met de lichtbatterij.
Een bistabiele relais gebruikt geen stroom in welke toestand hij ook staat (brug aan of brug uit). Enkel tijdens
het omschakelen is korte tijd een stroom nodig (pulsje van ca. 0,2 seconden).
De beide spoelen van het bistabiel relais worden gestuurd met een BC337 transistor, deze is hiervoor sterk genoeg.
Merk op dat de spoelen via het 12V circuit gestuurd worden en niet via het 5V circuit.
Relay 3 in de schakeling stelt eigenlijk de "uit" spoel voor, Relay 2 de "aan" spoel.
Relay 1, niet strikt noodzakelijk, dient eigenlijk om tijdens het omschakelen van de brug een eventueel extern
alarsysteem even te deactiveren. Dit komt uitsluitend omdat ik een alarmsysteem heb dat reageert op plotselinge
veranderingen van de spanning en het omschakelen van de brug zou het alarm laten afgaan. Je kan Relay 1 dus rustig
weglaten als je een dergelijke interface met je alarmsysteem niet nodig hebt.
Men kan ten allen tijde met een drukknop de brug manueel bedienen met behulp van SW1 (maar alleen indien de spanning
in het zweef-bereik zit t.t.z. tussen ca. 12,4 en 13,5 Volt).
Het relais is dus zoals gezegd een bistabiel relais van een zo fors mogelijke uitvoering, bijvoorbeeld
Conrad bestelnr. 504173 - 62.
Deze schakelt tot 16A. De software zorgt voor de aansturing.
Indien men een bistabiel relais zou kunnen vinden van een nog hogere contact)amperage (vb. 30A) wat mij dus niet gelukt is,
zou men de schakeling ook kunnen gebruiken om een brug te leggen tijdens het rijden. Een software aanpassing is dan wel
noodzakelijk.
Handig is ook om twee LEDs (met voorschakelweerstand) parallel op de spoelen van het relais te zetten (niet getekend
in het schema) zodat men kan zien wanneer omgeschakeld wordt (kortstondig aangaan van de LED).
;;
;; ;; Zonnebatterij automaat, a PIC 16F84 program to switch two lead-acid batteries in parallel ;; when there is enough sunlight. ;; ;; Copyright (C) 2000 Geert Van Espen (geert@vanespen.com) ;; ;; LIST P=16F84 errorlevel 0,-305 processor 16f84 include "p16f84.inc" __CONFIG _CP_OFF & _RC_OSC & _PWRTE_ON & _WDT_ON ; ; ; ; ; commando om dit project naar de pic te sturen: ; TOPIC -RWG SOLARSW.HEX ; ; ; ; ; ; current settings: low level = 12.29 V ; high level = 13.45 V ; ; general purpose register allocation werk equ 0x0c ; werkregister t1 equ 0x0d ; telwerk 1 t2 equ 0x0e ; telwerk 2 TIJDl equ 0x10 ; to keep track of time TIJDh equ 0x11 ddd equ 0x13 ; debug only KLAPPERTIJD0 equ 0x14 ; hysteresis 0 KLAPPERTIJD1 equ 0x15 ; hysteresis 1 KLAPPERTIJD2 equ 0x16 ; hysteresis 2 KLAPPERTIJD3 equ 0x17 ; hysteresis 3 RB0_STAND equ 0x18 ; 0=uit 1=aan RB1_STAND equ 0x19 ; 0=uit 1=aan RB2_STAND equ 0x1a ; 0=uit 1=aan RB3_STAND equ 0x1b ; 0=uit 1=aan tempvar equ 0x1c ; Wl equ 0x20 ; Wh equ 0x21 ; BRUG equ 0x22 ; 0 = geen doorkoppeling batterijen ; 1 = wel doorkoppeling batterijen CONTACT equ 0x23 ; 0 = contactsleutel uit ; 1 = contactsleutel aan PrevRB0 equ 0x24 ; vorige RB0 situatie PrevRB1 equ 0x25 ; vorige RB1 situatie PrevRB2 equ 0x26 ; vorige contact situatie PrevBtn equ 0x27 ; vorige pushbutton situatie ; tijdconstanten ;;;;;;;;;;;;;;;; m_input_a equ b'00000000' ; input mask, which bits are input m_input_b equ b'11111111' ; org 0x00 ; reset vector goto main dt "2000-10-10 geert@vanespen.com Zonnebatterij automaat" ;*********************************************************************** ;* * ;* initialise * ;* * ;*********************************************************************** initialise: ; set up ports MOVLW 0 ; TRIS 5 ; MOVLW 0x0F ; TRIS 6 ; MOVLW 0x80 ; OPTION ; clrf TIJDl ; initialisaties clrf TIJDh ; clrf KLAPPERTIJD0 ; clrf KLAPPERTIJD1 ; clrf KLAPPERTIJD2 ; clrf KLAPPERTIJD3 ; clrf RB0_STAND ; clrf RB1_STAND ; clrf RB2_STAND ; clrf RB3_STAND ; clrf BRUG ; clrf CONTACT ; clrf PrevRB0 ; clrf PrevRB1 ; clrf PrevRB2 ; clrf PrevBtn ; clrf PORTA ; UIT laag clrf PORTB ; uitgang even aan en uit laten knipperen om te laten zien dat het ; apparaat werkt movlw 0xFE ; startwaarde movwf PORTA ; movlw 6 ; knipper 3 keer movwf t1 ; functiontest: movlw 0x19 ; wacht halve seconde call wachtlus ; movlw 0xFF ; xorwf PORTA, f ; decfsz t1, f ; goto functiontest ; clrf PORTA ; UIT laag retlw 0 ;*********************************************************************** ;* * ;* wachtlus * ;* * ;*********************************************************************** wachtlus: ; wacht x keer 18 milliseconden, met x in w movwf werk ; zet w in werk ; debug only ; movlw 1 ; movwf werk slapertje: sleep ; decfsz werk, f ; goto slapertje ; retlw 0 ; ;*********************************************************************** ;* * ;* test_portRB0 * ;* * ;*********************************************************************** ; hysteresis voor poort RB0: als RB0 een tijdje 0 is wordt RB0_STAND ; ook 0; als RB0 1 is wordt RB0_STAND onmiddellijk 1 test_portRB0: movf PORTB, w ; w = PORTB andlw 1 ; we willen alleen RB0 movwf tempvar ; movf tempvar, w ; btfss tempvar, 0 ; goto test0_low ; movlw 1 ; movwf RB0_STAND ; clrf KLAPPERTIJD0 ; KLAPPERTIJD0 = 0 retlw 0 ; test0_low: subwf RB0_STAND, w ; btfss STATUS, Z ; RB0 input = RB0_STAND? goto test0_hyst1 ; clrf KLAPPERTIJD0 ; ja: KLAPPERTIJD0 = 0 goto test0_hyst2 ; test0_hyst1: incf KLAPPERTIJD0, f ; neen: verhoog KLAPPERTIJD0 test0_hyst2: btfss KLAPPERTIJD0, 2 ; KLAPPERTIJD0 hoog? goto test0_hyst3 ; neen: gedaan movf tempvar, w ; movwf RB0_STAND ; ja: RB0_STAND = RB0 input clrf KLAPPERTIJD0 ; KLAPPERTIJD0 = 0 test0_hyst3: retlw 0 ; ;*********************************************************************** ;* * ;* test_portRB1 * ;* * ;*********************************************************************** ; hysteresis voor poort RB1: als RB1 een tijdje 0 is wordt RB1_STAND ; ook 0; als RB1 1 is wordt RB1_STAND onmiddellijk 1 test_portRB1: movf PORTB, w ; w = PORTB andlw 2 ; we willen alleen RB1 movwf tempvar ; bcf STATUS, C ; rrf tempvar, f ; movf tempvar, w ; btfss tempvar, 0 ; goto test1_low ; movlw 1 ; movwf RB1_STAND ; clrf KLAPPERTIJD1 ; KLAPPERTIJD1 = 0 retlw 0 ; test1_low: subwf RB1_STAND, w ; btfss STATUS, Z ; RB1 input = RB1_STAND? goto test1_hyst1 ; clrf KLAPPERTIJD1 ; ja: KLAPPERTIJD1 = 0 goto test1_hyst2 ; test1_hyst1: incf KLAPPERTIJD1, f ; neen: verhoog KLAPPERTIJD1 test1_hyst2: btfss KLAPPERTIJD1, 2 ; KLAPPERTIJD1 hoog? goto test1_hyst3 ; neen: gedaan movf tempvar, w ; movwf RB1_STAND ; ja: RB1_STAND = RB1 input clrf KLAPPERTIJD1 ; KLAPPERTIJD1 = 0 test1_hyst3: retlw 0 ; ;*********************************************************************** ;* * ;* test_portRB2 * ;* * ;*********************************************************************** ; hysteresis voor poort RB2: als RB2 een tijdje 1 is wordt RB2_STAND ; ook 1; als RB2 een tijdje nul is wordt RB2_STAND ook nul test_portRB2: movf PORTB, w ; w = PORTB andlw 0x04 ; we willen alleen RB2 movwf tempvar ; bcf STATUS, C ; rrf tempvar, f ; rrf tempvar, f ; movf tempvar, w ; subwf RB2_STAND, w ; btfss STATUS, Z ; RB2 input = RB2_STAND? goto test2_hyst1 ; clrf KLAPPERTIJD2 ; ja: KLAPPERTIJD2 = 0 goto test2_hyst2 ; test2_hyst1: incf KLAPPERTIJD2, f ; neen: verhoog KLAPPERTIJD2 test2_hyst2: btfss KLAPPERTIJD2, 1 ; KLAPPERTIJD2 hoog? goto test2_hyst3 ; neen: gedaan movf tempvar, w ; movwf RB2_STAND ; ja: RB2_STAND = RB2 input clrf KLAPPERTIJD2 ; KLAPPERTIJD2 = 0 test2_hyst3: retlw 0 ; ;*********************************************************************** ;* * ;* test_portRB3 * ;* * ;*********************************************************************** ; hysteresis voor poort RB3: als RB3 een tijdje 1 is wordt RB3_STAND ; ook 1; als RB3 een tijdje nul is wordt RB3_STAND ook nul test_portRB3: movf PORTB, w ; w = PORTB andlw 0x08 ; we willen alleen RB3 movwf tempvar ; bcf STATUS, C ; rrf tempvar, f ; rrf tempvar, f ; rrf tempvar, f ; movf tempvar, w ; subwf RB3_STAND, w ; btfss STATUS, Z ; RB3 input = RB3_STAND? goto test3_hyst1 ; clrf KLAPPERTIJD3 ; ja: KLAPPERTIJD3 = 0 goto test3_hyst2 ; test3_hyst1: incf KLAPPERTIJD3, f ; neen: verhoog KLAPPERTIJD3 test3_hyst2: btfss KLAPPERTIJD3, 2 ; KLAPPERTIJD3 hoog? goto test3_hyst3 ; neen: gedaan movf tempvar, w ; movwf RB3_STAND ; ja: RB3_STAND = RB3 input clrf KLAPPERTIJD3 ; KLAPPERTIJD3 = 0 test3_hyst3: retlw 0 ; ;*********************************************************************** ;*********************************************************************** ;* * ;* programma * ;* * ;*********************************************************************** main: btfsc STATUS, NOT_TO ; if this is a reset or power-up ... call initialise ; set port drivers and WDT prescaler movlw 1 ; veronderstel contact aan movwf CONTACT ; movlw 3 ; movwf PrevRB0 ; movwf PrevRB1 ; movwf PrevRB2 ; movwf PrevBtn ; start: main_loop: ; ; LAGE DREMPELSPANNING (poort RB0) ; call test_portRB0 ; test spanning op poort RB0 movf PrevRB0, w ; test of RB0_STAND veranderd is subwf RB0_STAND, w ; ;;;;; btfsc STATUS, Z ; is de stand veranderd? ;;;;; goto test0_af ; ; veranderd movf RB0_STAND, w ; ja, de stand is veranderd movwf PrevRB0 ; btfsc RB0_STAND, 0 ; is spanning laag? goto test0_af ; neen, gedaan btfss BRUG, 0 ; ja: test of brug al af stond goto test0_af ; brug af: gedaan bsf PORTA, 2 ; spanning laag: alarm-disable relais bsf PORTA, 0 ; en RA0 een tijdje aanzetten movlw 0xc ; wacht fractie seconde call wachtlus ; clrf BRUG ; bewaar huidige toestand bcf PORTA, 0 ; poorten terug uitzetten bcf PORTA, 2 ; movlw 0x6f ; wacht 2 seconden call wachtlus ; test0_af: ; ; HOGE DREMPELSPANNING (poort RB1) ; btfsc CONTACT, 0 ; als contact aan, goto test1_af ; dan nooit brug maken! call test_portRB1 ; test spanning op poort RB1 movf PrevRB1, w ; subwf RB1_STAND, w ; ;;;;; btfsc STATUS, Z ; is de stand veranderd? ;;;;; goto test1_af ; ; veranderd movf RB1_STAND, w ; ja, de stand is veranderd movwf PrevRB1 ; btfss RB1_STAND, 0 ; is spanning hoog? goto test1_af ; neen, gedaan btfsc BRUG, 0 ; ja: test of brug al aan stond goto test1_af ; brug aan: gedaan bsf PORTA, 2 ; spanning hoog: alarm-disable relais bsf PORTA, 1 ; en RA1 een tijdje aanzetten movlw 0xc ; wacht fractie seconde call wachtlus ; bsf BRUG, 0 ; bewaar huidige toestand bcf PORTA, 1 ; poorten terug uitzetten bcf PORTA, 2 ; movlw 0x6f ; wacht 2 seconden call wachtlus ; test1_af: ; ; CONTACTSLEUTEL (poort RB2) ; ContactSleutel: call test_portRB2 ; test spanning op poort RB2 movf PrevRB2, w ; subwf RB2_STAND, w ; btfsc STATUS, Z ; is de stand veranderd? goto test2_af ; ; veranderd movf RB2_STAND, w ; ja, de stand is veranderd movwf PrevRB2 ; btfsc RB2_STAND, 0 ; is contact aan? goto test2_aan ; clrf CONTACT ; neen: bewaar huidige toestand bsf PrevRB0, 3 ; herinitialiseer spanningstesten bsf PrevRB1, 3 ; goto test2_af ; test2_aan: bsf CONTACT, 0 ; bewaar huidige toestand bsf PORTA, 2 ; alarm-disable relais en bsf PORTA, 0 ; RA0 een tijdje aanzetten movlw 0xc ; wacht fractie seconde call wachtlus ; clrf BRUG ; bewaar huidige toestand bcf PORTA, 0 ; poorten terug uitzetten bcf PORTA, 2 ; movlw 0xfe ; wacht 5 seconden call wachtlus ; test2_af: ; ; PUSHBUTTON (poort RB3) ; btfss CONTACT, 0 ; als contact aan, goto PushButton ; dan nooit brug maken! clrf PrevBtn ; goto PushButton_samen; PushButton: call test_portRB3 ; als pushbutton gedrukt is, movf PrevBtn, w ; dan toggelen subwf RB3_STAND, w ; btfsc STATUS, Z ; is de stand veranderd? goto PushButton_gelijk; PushButton_changed: movf RB3_STAND, w ; ja: PrevBtn = RB3_STAND movwf PrevBtn ; btfss RB3_STAND, 0 ; is pushbutton gedrukt? goto PushButton_af ; movlw 1 ; ja: toggle BRUG xorwf BRUG, f ; ; reflect BRUG value onto output ports btfss BRUG, 0 ; BRUG waarde testen goto PushButton_Reflect_uit; PushButton_Reflect_aan: bsf PORTA, 2 ; alarm-disable relais en bsf PORTA, 1 ; RA1 een tijdje aanzetten movlw 0xc ; wacht fractie seconde call wachtlus ; bcf PORTA, 1 ; poorten terug uitzetten bcf PORTA, 2 ; goto PushButton_samen; PushButton_Reflect_uit: bsf PORTA, 2 ; alarm-disable relais en bsf PORTA, 0 ; RA0 een tijdje aanzetten movlw 0xc ; wacht fractie seconde call wachtlus ; bcf PORTA, 0 ; poorten terug uitzetten bcf PORTA, 2 ; goto PushButton_samen; PushButton_samen: PushButton_gelijk: goto PushButton_af ; PushButton_af: movlw 0x2 ; wacht fractie seconde call wachtlus ; goto start ; ;; ;; end
Download bron code (assembler) Download hex bestand (machine code)